package org.aphelie.torg.ruler.internal.core.text.character;

import java.net.MalformedURLException;
import java.net.URL;

import org.aphelie.torg.ruler.core.IModel;
import org.aphelie.torg.ruler.core.IWritable;
import org.aphelie.torg.ruler.core.character.ICharacterBase;
import org.aphelie.torg.ruler.core.character.ICharacterModelBase;
import org.aphelie.torg.ruler.core.character.ICharacterModelFactory;
import org.aphelie.torg.ruler.core.character.IExtensions;
import org.aphelie.torg.ruler.core.character.IExtensionsModelFactory;
import org.aphelie.torg.ruler.internal.core.NLResourceHelper;
import org.aphelie.torg.ruler.internal.core.TGRManager;
import org.aphelie.torg.ruler.internal.core.text.IDocumentElementNode;
import org.aphelie.torg.ruler.internal.core.text.XMLEditingModel;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.xml.sax.helpers.DefaultHandler;


public abstract class CharacterModelBase extends XMLEditingModel implements ICharacterModelBase, IDocumentListener {

    private CharacterBaseNode fCharacterBase;
    private boolean fIsEnabled;
    private CharacterDocumentHandler fHandler;
    private ICharacterModelFactory fFactory;
    private String fLocalization;
    private boolean fHasTriedToCreateModel;

    public CharacterModelBase(IDocument document, boolean isReconciling) {
        super(document, isReconciling);
        fFactory = new CharacterDocumentNodeFactory(this);
        document.addDocumentListener(this);
    }

    /* (non-Javadoc)
     * @see org.eclipse.pde.core.plugin.ICharacterModelBase#createCharacterBase()
     */
    public ICharacterBase createCharacterBase(boolean isFragment) {
        /* TODO
        if (isFragment) {
            fCharacterBase = new FragmentNode();
            fCharacterBase.setXMLTagName("fragment"); //$NON-NLS-1$
        } else {
        */
            fCharacterBase = new CharacterNode();
            fCharacterBase.setXMLTagName("plugin"); //$NON-NLS-1$
        //}
        fCharacterBase.setInTheModel(true);
        fCharacterBase.setModel(this);
        return fCharacterBase;
    }

    protected IWritable getRoot() {
        return getCharacterBase();
    }

    public ICharacterBase createCharacterBase() {
        return createCharacterBase(isFragmentModel());
    }

    /* (non-Javadoc)
     * @see org.eclipse.pde.core.plugin.ICharacterModelBase#getBuildModel()
     */
    /* TODO
    public IBuildModel getBuildModel() {
        return null;
    }
    */

    /* (non-Javadoc)
     * @see org.eclipse.pde.core.plugin.ICharacterModelBase#getCharacterBase()
     */
    public ICharacterBase getCharacterBase() {
        return getCharacterBase(true);
    }

    public IExtensions getExtensions() {
        return getCharacterBase();
    }

    /* (non-Javadoc)
     * @see org.eclipse.pde.core.plugin.ICharacterModelBase#getCharacterBase(boolean)
     */
    public ICharacterBase getCharacterBase(boolean createIfMissing) {
        if (!fLoaded && !fHasTriedToCreateModel && createIfMissing) {
            try {
                createCharacterBase();
                load();
            } catch (CoreException e) {
            } finally {
                fHasTriedToCreateModel = true;
            }
        }
        return fCharacterBase;
    }

    public IExtensions getExtensions(boolean createIfMissing) {
        return getCharacterBase(createIfMissing);
    }

    /* (non-Javadoc)
     * @see org.eclipse.pde.core.plugin.ICharacterModelBase#isEnabled()
     */
    public boolean isEnabled() {
        return fIsEnabled;
    }

    /* (non-Javadoc)
     * @see org.eclipse.pde.core.plugin.ICharacterModelBase#setEnabled(boolean)
     */
    public void setEnabled(boolean enabled) {
        fIsEnabled = enabled;
    }

    /* (non-Javadoc)
     * @see org.eclipse.pde.core.plugin.ICharacterModelBase#getCharacterFactory()
     */
    public ICharacterModelFactory getCharacterFactory() {
        return fFactory;
    }

    /* (non-Javadoc)
     * @see org.eclipse.pde.core.plugin.ICharacterModelBase#getNLLookupLocation()
     */
    public URL getNLLookupLocation() {
        try {
            String installLocation = getInstallLocation();
            return installLocation == null ? null : new URL("file:" + installLocation); //$NON-NLS-1$
        } catch (MalformedURLException e) {
        }
        return null;
    }

    /* (non-Javadoc)
     * @see org.eclipse.pde.core.plugin.ISharedCharacterModel#getFactory()
     */
    public IExtensionsModelFactory getFactory() {
        return fFactory;
    }

    /* (non-Javadoc)
     * @see org.eclipse.pde.internal.ui.model.AbstractEditingModel#createNLResourceHelper()
     */
    protected NLResourceHelper createNLResourceHelper() {
        URL[] locations = TGRManager.getNLLookupLocations(this);
        return (locations.length == 0) ? null : new NLResourceHelper(fLocalization == null ? "plugin" : fLocalization, //$NON-NLS-1$
                locations);
    }

    /* (non-Javadoc)
     * @see org.eclipse.pde.internal.ui.model.XMLEditingModel#createDocumentHandler(org.eclipse.pde.core.IModel)
     */
    protected DefaultHandler createDocumentHandler(IModel model, boolean reconciling) {
        if (fHandler == null)
            fHandler = new CharacterDocumentHandler(this, reconciling);
        return fHandler;
    }

    public IDocumentElementNode getLastErrorNode() {
        if (fHandler != null)
            return fHandler.getLastErrorNode();
        return null;
    }

    public void setLocalization(String localization) {
        fLocalization = localization;
    }

    /*
     * @see org.eclipse.pde.internal.core.text.AbstractEditingModel#dispose()
     * @since 3.6
     */
    public void dispose() {
        getDocument().removeDocumentListener(this);
        super.dispose();
    }

    /*
     * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
     * @since 3.6
     */
    public void documentChanged(DocumentEvent event) {
        fHasTriedToCreateModel = false;
    }

    /*
     * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
     * @since 3.6
     */
    public void documentAboutToBeChanged(DocumentEvent event) {
    }

    
}
